import time
import psutil
import logging
from typing import List, Optional
from dataclasses import dataclass

@dataclass
class PerformanceMetrics:
    start_time: float
    end_time: float
    cpu_percent: float
    memory_percent: float
    memory_used: float
    io_read_bytes: int
    io_write_bytes: int
    items_processed: int
    total_items: int

class PerformanceMonitor:
    def __init__(self):
        self.logger = logging.getLogger(__name__)
        self.metrics_history: List[PerformanceMetrics] = []
        self.current_metrics: Optional[PerformanceMetrics] = None
        self.process = psutil.Process()
        self.start_io_counters = None

    def start_monitoring(self, total_items: int = 0):
        """开始监控性能指标"""
        self.start_io_counters = psutil.disk_io_counters()
        self.current_metrics = PerformanceMetrics(
            start_time=time.time(),
            end_time=0,
            cpu_percent=0,
            memory_percent=0,
            memory_used=0,
            io_read_bytes=0,
            io_write_bytes=0,
            items_processed=0,
            total_items=total_items
        )

    def update_progress(self, items_processed: int):
        """更新处理进度"""
        if self.current_metrics:
            self.current_metrics.items_processed = items_processed
            self._update_current_metrics()

    def stop_monitoring(self):
        """停止监控并记录最终指标"""
        if self.current_metrics:
            self.current_metrics.end_time = time.time()
            self._update_current_metrics()
            self.metrics_history.append(self.current_metrics)
            self._log_metrics(self.current_metrics)
            self.current_metrics = None

    def _update_current_metrics(self):
        """更新当前性能指标"""
        if self.current_metrics:
            self.current_metrics.cpu_percent = self.process.cpu_percent()
            memory_info = self.process.memory_info()
            self.current_metrics.memory_used = memory_info.rss / 1024 / 1024  # MB
            self.current_metrics.memory_percent = self.process.memory_percent()

            if self.start_io_counters:
                current_io = psutil.disk_io_counters()
                self.current_metrics.io_read_bytes = current_io.read_bytes - self.start_io_counters.read_bytes
                self.current_metrics.io_write_bytes = current_io.write_bytes - self.start_io_counters.write_bytes

    def _log_metrics(self, metrics: PerformanceMetrics):
        """记录性能指标"""
        duration = metrics.end_time - metrics.start_time
        items_per_second = metrics.items_processed / duration if duration > 0 else 0

        self.logger.info(f"性能指标统计:")
        self.logger.info(f"处理时间: {duration:.2f} 秒")
        self.logger.info(f"处理项目数: {metrics.items_processed}/{metrics.total_items}")
        self.logger.info(f"处理速度: {items_per_second:.2f} 项目/秒")
        self.logger.info(f"CPU使用率: {metrics.cpu_percent:.1f}%")
        self.logger.info(f"内存使用: {metrics.memory_used:.1f} MB ({metrics.memory_percent:.1f}%)")
        self.logger.info(f"IO读取: {metrics.io_read_bytes / 1024 / 1024:.1f} MB")
        self.logger.info(f"IO写入: {metrics.io_write_bytes / 1024 / 1024:.1f} MB")

    def get_average_metrics(self) -> Optional[PerformanceMetrics]:
        """获取平均性能指标"""
        if not self.metrics_history:
            return None

        total_duration = sum(m.end_time - m.start_time for m in self.metrics_history)
        total_items = sum(m.items_processed for m in self.metrics_history)
        avg_cpu = sum(m.cpu_percent for m in self.metrics_history) / len(self.metrics_history)
        avg_memory = sum(m.memory_used for m in self.metrics_history) / len(self.metrics_history)
        total_io_read = sum(m.io_read_bytes for m in self.metrics_history)
        total_io_write = sum(m.io_write_bytes for m in self.metrics_history)

        return PerformanceMetrics(
            start_time=self.metrics_history[0].start_time,
            end_time=self.metrics_history[-1].end_time,
            cpu_percent=avg_cpu,
            memory_percent=avg_memory / psutil.virtual_memory().total * 100,
            memory_used=avg_memory,
            io_read_bytes=total_io_read,
            io_write_bytes=total_io_write,
            items_processed=total_items,
            total_items=self.metrics_history[0].total_items
        )

    def export_metrics(self, file_path: str):
        """导出性能指标到文件"""
        if not self.metrics_history:
            return

        with open(file_path, 'w', encoding='utf-8') as f:
            f.write("性能指标报告\n")
            f.write("=" * 50 + "\n\n")
            
            # 写入总体统计
            avg_metrics = self.get_average_metrics()
            if avg_metrics:
                f.write("总体统计:\n")
                f.write(f"总处理时间: {avg_metrics.end_time - avg_metrics.start_time:.2f} 秒\n")
                f.write(f"总处理项目数: {avg_metrics.items_processed}\n")
                f.write(f"平均CPU使用率: {avg_metrics.cpu_percent:.1f}%\n")
                f.write(f"平均内存使用: {avg_metrics.memory_used:.1f} MB\n")
                f.write(f"总IO读取: {avg_metrics.io_read_bytes / 1024 / 1024:.1f} MB\n")
                f.write(f"总IO写入: {avg_metrics.io_write_bytes / 1024 / 1024:.1f} MB\n\n")

            # 写入详细历史记录
            f.write("详细历史记录:\n")
            f.write("-" * 50 + "\n")
            for i, metrics in enumerate(self.metrics_history, 1):
                duration = metrics.end_time - metrics.start_time
                f.write(f"批次 {i}:\n")
                f.write(f"  处理时间: {duration:.2f} 秒\n")
                f.write(f"  处理项目数: {metrics.items_processed}\n")
                f.write(f"  CPU使用率: {metrics.cpu_percent:.1f}%\n")
                f.write(f"  内存使用: {metrics.memory_used:.1f} MB\n")
                f.write(f"  IO读取: {metrics.io_read_bytes / 1024 / 1024:.1f} MB\n")
                f.write(f"  IO写入: {metrics.io_write_bytes / 1024 / 1024:.1f} MB\n")
                f.write("-" * 50 + "\n") 